#ifndef VENTANA_H_
#define VENTANA_H_

#include <GL/glut.h>
#include "handler.h"

class Ventana {
   private:
      int glut_id;
      bool iniciada;

      int x, y, w, h;

      Handler _handler;

      Ventana(const Ventana&);
      Ventana& operator=(const Ventana&);


      /*
       * Inicializa esta Ventana como la ventana Superior o
       * TopLevel en el sistema Glut.
       *
       * Luego inicializa a las (posibles) sub ventanas.
       *
       * Registra a esta Ventana como la TopLevel, registrando
       * ademas su metodo dibujar() y redimensionar() en el sistema
       * Glut.
       * */
   public:
      void iniciarVentanaPrincipal(const char *nombre) {
         glut_id = glutCreateWindow(nombre);
         iniciada = true;
         iniciar();

         Ventana::topLevel = this;

         glutDisplayFunc(Ventana::dibujar_callback);
         glutReshapeFunc(Ventana::redimensionar_callback);

         _handler.asignarManejadores();
      }
   private:

      /*
       * Elimina y libera los recursos asociados a esta Ventana
       * en el sistema Glut.
       * */
      void eliminar() {
         if(iniciada) {
            glutDestroyWindow(glut_id);
            iniciada = false;
         }
      }

      static Ventana* topLevel;

      /*
       * Callback para glutDisplayFunc 
       *
       * Llama al metodo dibujar() de la Ventana TopLevel 
       *
       * */
      static void dibujar_callback() {
         topLevel->dibujar();
         glutSwapBuffers();  
      }

      /*
       * Callback para glutReshapeFunc 
       *
       * Llama al metodo redimensionar() de la Ventana TopLevel 
       *
       * */
      static void redimensionar_callback(int w, int h) {
         topLevel->redimensionar(w, h);
         glutSwapBuffers();  
      }

   public:

      Ventana(int x, int y, int w, int h) : 
         glut_id(0),
         iniciada(false),
         x(x), y(y), w(w), h(h) {}

      virtual ~Ventana() {
         eliminar();
      }

      int ancho() { return w; }
      int alto() { return h; }

      Handler& handler() { return _handler; }

      virtual void dibujar() = 0;
      virtual void iniciar() {}
      virtual void redimensionar(int w, int h) {
         this->w = w;
         this->h = h;
      }

      static void refrescar() {
         glutPostRedisplay();
      }

      friend void run(Ventana& v, const char* nombre);
};


#endif
